﻿var fs = require("fs");

var Configure = function (option) {

    option = option || {}; // TODO? 扩展功能
    this._data = { };

    this.__defineGetter__("json", function () { return this._data; });
    this.__defineGetter__("data", function () { return this._data; });
};

Configure.prototype.parseText = function (sText) {
    var arr   = sText.split(/\r\n|\r|\n/); //行划分
    var stack = [this._data];

    for(var i = 0, len = arr.length; i < len; i++) {
        var line = arr[i].replace(/^[\s\t ]+|[\s\t ]+$/g, '');
        if (line.length == 0 || line[0] == "#") {
            continue;
        }

        //当前行为当前域下面的值
        if (line[0] != "<") {
            var options = line.split("=");
            var key     = options[0].replace(/^[\s\t ]+|[\s\t ]+$/g, '');
            var value   = options.length == 2?options[1].replace(/^[\s\t ]+|[\s\t ]+$/g, ''):undefined;

            stack[stack.length - 1][key] = value;
            continue;
        }

        //当前行为域的标识
        if (line[line.length - 1] != '>') {
            //域标识符有开头但没有结尾，则分析错误
            this.data = {};
            return false;
        }

        //当前行为域的结束
        if (line[1] == "/") {
            stack.pop();
            continue;
        }

        //当前行为域的开始
        var key     = line.substring(1, line.length - 1);
        var parent  = stack[stack.length - 1];

        if (parent.hasOwnProperty(key)) {
            //在当前域中已经有相同名字的域
            if (parent[key] instanceof Array) {
                parent[key].push({});
            } else {
                parent[key] = [parent[key], {}];
            }
            stack.push(parent[key][parent[key].length - 1]);
        } else {
            parent[key] = {};
            stack.push(parent[key]);
        }
    }

    return true;
};

Configure.prototype.parseFile = function (sFilePath, encoding, callback) {
    var callback = typeof(encoding) === "function"?encoding:callback;
    var encoding = typeof(encoding) === "string"  ?encoding:"utf8";
    var error = {code:0, message:"", exception:undefined};

    try {

        if (callback === undefined) {
            this.parseText(fs.readFileSync(sFilePath, encoding));
        } else {
            this.asyncParseFile(sFilePath, encoding, callback);
        }
    } catch (e) {
        error.code      = -1;
        error.message   = "read file fault";
        error.exception = e;
    }

    if (callback && error.code != 0) callback.call(null, error, this);
    return error.code == 0;
};

Configure.prototype.asyncParseFile = function (sFilePath, encoding, callback) {
    var self = this;
    fs.readFile(sFilePath, encoding, function (err, data){
        if (err) throw err;

        self.parseText(data);
        callback.call(null, {code:0, message:"success", exception:undefined}, self);
    });
};

Configure.prototype.get = function (key, DEFAULT_VALUE) {
    key = key.replace(/[\s\t ]+/g, '');
    key = key.replace(/\.{2,}/g, '.');

    var paths = [];
    var s = 0;
    for (var i = 0, finding = false, len = key.length; i < len; i++) {
        if (key[i] == '.' && !finding) {
            paths.push(key.substring(s, i));
            s = i + 1;
            continue;
        }

        if (key[i] == '<') {
            s = i;
            finding = true;
            continue;
        }

        if (key[i] == '>') {
            paths.push(key.substring(s + 1, i));
            s = i + 1;
            finding = false;
        }
    }
    if (s < key.length) {
        paths.push(key.substr(s));
    }

    var parent = this._data;
    for (var i = 0, len = paths.length; i < len; i++) {
        if (!parent.hasOwnProperty(paths[i])){
            return DEFAULT_VALUE;
        }

        if (i == len - 1) {
            return parent[paths[i].indexOf('<') == -1?paths[i]:substr(1, paths[i].length - 2)];
        }

        parent = parent[paths[i]];
    }
};

// 获取key所对应的对象中的类型为对象的属性名数组（非递归）
Configure.prototype.getDomain = function (key, DEFAULT_VALUE) {
    var domain = this.get(key, undefined);
    if (domain == undefined) {
        return DEFAULT_VALUE;
    }

    var maps = [];
    if (domain instanceof Object) {
        for (var key in domain) {
            if (domain[key] instanceof Object) {
                maps.push(key);
            }
        }
    }

    return maps;
};

// 获取key所对应的对象中的类型为对象的属性值数组（非递归）
Configure.prototype.getDomainValue = function(key, DEFAULT_VALUE)
{
    var arr = [];
    var keys = this.getDomain(key, []);
    for(var i = 0; i < keys.length; i++)
    {
        var k = keys[i];
        var v = this.get(key + '.<' + k + '>', undefined);
        if(v)
        {
            arr.push(v);
        }
    }

    return arr;
};

module.exports = Configure;